/*
* WINDOWS DISGUISER
* 
* Written by Marco Minerva, mailto:marco.minerva@gmail.com
* 
* This code is released under the Microsoft Public License (Ms-PL).
* A copy of this license is available at
* http://www.microsoft.com/opensource/licenses.mspx#Ms-PL
*/

using System;
using System.Text;
using System.Collections;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Collections.Generic;

namespace WindowsDisguiser
{
    public class Window
    {
        private IntPtr handle;
        /// <summary>
        /// Window Object's Public Properties
        /// </summary>
        public IntPtr Handle
        {
            get { return handle; }
        }

        private string title;
        public string Title
        {
            get { return title; }
        }

        private string processFileName;
        public string ProcessFileName
        {
            get { return processFileName; }
        }

        private int processId;
        public int ProcessId
        {
            get { return processId; }
        }

        /// <summary>
        /// Constructs a Window Object
        /// </summary>
        /// <param name="Title">Title Caption</param>
        /// <param name="hWnd">Handle</param>
        /// <param name="Process">Owning Process</param>
        public Window(string title, IntPtr handle, string processFileName, int processId)
        {
            this.title = title;
            this.handle = handle;
            this.processFileName = processFileName;
            this.processId = processId;
        }

        public override string ToString()
        {
            if (!string.IsNullOrEmpty(title))
                return title;
            return string.Empty;
        }
    }

    /// <summary>
    /// Collection used to enumerate Window Objects
    /// </summary>
    public class WindowsManager
    {
        #region Platform Invoke

        [DllImport("user32.dll")]
        private static extern int GetWindowText(int hWnd, StringBuilder title, int size);
        [DllImport("user32.dll")]
        private static extern int EnumWindows(EnumWindowsProc ewp, int lParam);
        [DllImport("user32.dll")]
        private static extern bool IsWindowVisible(int hWnd);
        [DllImport("user32.dll")]
        private static extern IntPtr GetWindowThreadProcessId(int hWnd, out int ProcessId);

        #endregion

        //delegate used for EnumWindows() callback function
        private delegate bool EnumWindowsProc(int hWnd, int lParam);
        private List<Window> windowList;

        /// <summary>
        /// Collection Constructor
        /// </summary>
        public WindowsManager()
        {
            windowList = new List<Window>();
        }

        public Window[] GetWindows()
        {
            windowList.Clear();

            //Declare a callback delegate for EnumWindows() API call.
            EnumWindowsProc ewp = new EnumWindowsProc(EvalWindow);
            //Enumerate all Windows.
            EnumWindows(ewp, 0);

            return windowList.ToArray();
        }

        //EnumWindows CALLBACK function
        private bool EvalWindow(int hWnd, int lParam)
        {
            if (!IsWindowVisible(hWnd))
                return true;

            StringBuilder title = new StringBuilder(256);
            GetWindowText(hWnd, title, title.Capacity);
            if (title.Length == 0)
                return true;

            int processId = 0;
            string processName = null;
            GetWindowThreadProcessId(hWnd, out processId);
            if (processId > 0)
            {
                try
                {
                    processName = Process.GetProcessById(processId).MainModule.FileName;
                }
                catch { }
            }

            windowList.Add(new Window(title.ToString(), (IntPtr)hWnd, processName, processId));
            return true;
        }
    }
}
